-- 碎片逻辑
local ItemExcel = require("excel.item")
local DropExcel = require("excel.drop")
local HeroExcel = require("excel.hero")
local Lang = require("common.Lang")
local Msg = require("core.Msg")
local HeroGrid = require("hero.HeroGrid")
local HeroDefine = require("hero.HeroDefine")
local HeroLogic = require("hero.HeroLogic")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local DropSpecial = require("bag.DropSpecial")
local Grid = require("bag.Grid")
local Broadcast = require("broadcast.Broadcast")


SUMMON_TYPE_TARGET    = 1 -- 指定目标兑换
SUMMON_TYPE_DROP      = 2 -- 随机掉落表兑换
SUMMON_TYPE_HERO_SP   = 3 -- 英雄条件兑换
SUMMON_TYPE_SHENQI_SP = 4 -- 神器条件兑换

SUMMON_SUBTYPE_HERO = 1 -- 英雄
SUMMON_SUBTYPE_EQUIP = 2 -- 装备
SUMMON_SUBTYPE_SKIN = 3  -- 皮肤

-- 查询
function query(human, itemID)
	local itemConfig = ItemExcel.item[itemID]
	if itemConfig == nil then return end
	if itemConfig.get[1] ~= SUMMON_TYPE_TARGET then
		return
	end 
	if itemConfig.get[2] ~= SUMMON_SUBTYPE_HERO then
		return
	end 
	
	local heroID = itemConfig.get[3]
	local heroGrid = HeroGrid.getCacheHeroGridTujian(heroID)
	if not heroGrid then return end

	local msgRet = Msg.gc.GC_SUIPIAN_HERO_QUERY
	msgRet.id = itemID
	HeroGrid.makeHeroSimple(msgRet.heroSimple, heroGrid, nil, human, nil, true)	
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)	
end

-- 召唤
function summon(human, itemID, itemUseCnt)
	if human.db.bag[itemID] == nil or human.db.bag[itemID] < itemUseCnt then
		return
	end
	
	local itemConfig = ItemExcel.item[itemID]
	if itemConfig == nil then
		return
	end
	
	if itemConfig.get[1] ~= SUMMON_TYPE_TARGET 
		and itemConfig.get[1] ~= SUMMON_TYPE_DROP 
		and itemConfig.get[1] ~= SUMMON_TYPE_HERO_SP 
		and itemConfig.get[1] ~= SUMMON_TYPE_SHENQI_SP then	
		return
	end
	if itemConfig.get[2] ~= SUMMON_SUBTYPE_HERO and itemConfig.get[2] ~= SUMMON_SUBTYPE_EQUIP then
		return
	end
	
	local leftHeroBox =  HeroLogic.getEmptyCnt(human)
	
    if itemConfig.get[2] ~= SUMMON_SUBTYPE_EQUIP then
        if leftHeroBox <= 0 then 
           return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
        end
    end

	local realItemCnt = math.floor(itemUseCnt/itemConfig.fullCnt)
	if realItemCnt < 1 then
		return
	end
	if realItemCnt * itemConfig.fullCnt ~= itemUseCnt then
		return
	end

	local isHero = 0
	local outItemIDList = nil
	local targetID = nil
	if itemConfig.get[1] == SUMMON_TYPE_TARGET then
        -- 召唤数量大于剩余格子数，将真实召唤数量换成剩余格子数
        local leftHeroBox =  HeroLogic.getEmptyCnt(human)
        if realItemCnt > leftHeroBox then
            realItemCnt = leftHeroBox
        end
		-- 指定目标
		targetID = itemConfig.get[3]
	elseif itemConfig.get[1] == SUMMON_TYPE_DROP then
    
        -- 召唤数量大于剩余格子数，将真实召唤数量换成剩余格子数
		if itemConfig.get[2] ~= SUMMON_SUBTYPE_EQUIP then
			local leftHeroBox =  HeroLogic.getEmptyCnt(human)
			if realItemCnt > leftHeroBox then
				realItemCnt = leftHeroBox
			end
		end

		-- 掉落表随机掉落
		for i = 1, realItemCnt do
			local dropID = itemConfig.get[3]
			targetID = getDropTargetID(dropID)
			outItemIDList = outItemIDList or {}
			outItemIDList[targetID] = outItemIDList[targetID] or 0
			outItemIDList[targetID] = outItemIDList[targetID] + 1
		end
	elseif itemConfig.get[1] == SUMMON_TYPE_HERO_SP then
    
        
        -- 召唤数量大于剩余格子数，将真实召唤数量换成剩余格子数
        local leftHeroBox =  HeroLogic.getEmptyCnt(human)
        if realItemCnt > leftHeroBox then
            realItemCnt = leftHeroBox
        end

		-- 英雄条件兑换
		local dropTable = DropSpecial.getDropHeroTable(itemConfig.get[3][1], itemConfig.get[3][2], itemConfig.get[3][3])
		for i = 1, realItemCnt do
			local randTemp = math.random(1, #dropTable)
			targetID = dropTable[randTemp]
			outItemIDList = outItemIDList or {}
			outItemIDList[targetID] = outItemIDList[targetID] or 0
			outItemIDList[targetID] = outItemIDList[targetID] + 1
		end
	elseif itemConfig.get[1] == SUMMON_TYPE_SHENQI_SP then
		-- 神器条件兑换
		local dropTable = DropSpecial.getDropEquipTable(itemConfig.get[3][1], itemConfig.get[3][2], itemConfig.get[3][3], itemConfig.get[3][4])
		for i = 1, realItemCnt do
			local randTemp = math.random(1, #dropTable)
			targetID = dropTable[randTemp]
			outItemIDList = outItemIDList or {}
			outItemIDList[targetID] = outItemIDList[targetID] or 0
			outItemIDList[targetID] = outItemIDList[targetID] + 1
		end
	end
	
	if targetID == nil and outItemIDList == nil then
		assert(nil)
	end
    local realSuiPianCnt = realItemCnt * itemConfig.fullCnt
	BagLogic.delItem(human, itemID, realSuiPianCnt, "item_summon")
	
	local fenJieList = nil
	local itemList = {}
	if itemConfig.get[2] == SUMMON_SUBTYPE_HERO then
		isHero = 1
		if outItemIDList then
			-- 多个id
			for k, v in pairs(outItemIDList) do
				local _, fjlist = HeroLogic.addHero(human, k,nil, v, "item_summon")
                local heroID = k
                local hero = HeroExcel.hero[heroID]
                if fjlist and type(fjlist) == "table" then
                	for fjItemID, fjItemCnt in pairs(fjlist) do
                		fenJieList = fenJieList or {}
                		fenJieList[fjItemID] = (fenJieList[fjItemID] or 0) + fjItemCnt
                	end
                end
			end
		else
			-- 单个id
			local _, fjlist = HeroLogic.addHero(human, targetID,nil, realItemCnt, "item_summon")
            local heroID = targetID
            local hero = HeroExcel.hero[heroID]
            if fjlist and type(fjlist) == "table" then
            	for fjItemID, fjItemCnt in pairs(fjlist) do
            		fenJieList = fenJieList or {}
            		fenJieList[fjItemID] = (fenJieList[fjItemID] or 0) + fjItemCnt
            	end
            end
		end
	else
		if outItemIDList then
			-- 多个id
			for k, v in pairs(outItemIDList) do
				BagLogic.addItem(human, k, v, "item_summon")
				itemList[k] = itemList[k] or 0
				itemList[k] = itemList[k] + v
			end
		else
			-- 单个id
			BagLogic.addItem(human, targetID, realItemCnt, "item_summon")
			itemList[targetID] = itemList[targetID] or 0
			itemList[targetID] = itemList[targetID] + realItemCnt
		end
	end
	
	BagLogic.sendItemGetList(human, itemList, "item_summon")
	local msgRet = Msg.gc.GC_SUIPIAN_SUMMON
	msgRet.isHero = isHero
	msgRet.list[0] = 0
	msgRet.heroList[0] = 0
	msgRet.fenJieList[0] = 0

	local netList = (isHero == 1) and msgRet.heroList or msgRet.list
	
	if outItemIDList then
		-- 多个id
		for k, v in pairs(outItemIDList) do
			netList[0] = netList[0] + 1
			makeResultItemData(netList[netList[0]], k, v, isHero)
		end
	else
		netList[0] = netList[0] + 1
		makeResultItemData(netList[netList[0]], targetID, realItemCnt, isHero)
	end
	if fenJieList then
		for fjItemID, fjItemCnt in pairs(fenJieList) do
			msgRet.fenJieList[0] = msgRet.fenJieList[0] + 1
			Grid.makeItem(msgRet.fenJieList[msgRet.fenJieList[0]], fjItemID, fjItemCnt)
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

function makeResultItemData(net, id, cnt, isHero)
	if isHero == 1 then
		HeroGrid.makeHeroSimpleByID(net, id)
		net.cnt = cnt
	else
		Grid.makeItem(net, id, cnt)
	end
end

-- 根据掉落id 获取id
function getDropTargetID(dropID)
	local dropConfig = DropExcel.dropSuipian[dropID]
	if dropConfig == nil then
		return
	end
	
	-- 计算总权重
	local totalWeight = 0
    for k, v in ipairs(dropConfig.dropRule) do
        local weight = v[2]
	    totalWeight = totalWeight + weight
    end

    local heroWeight = nil
	local r = math.random(1, totalWeight)
	for k, v in ipairs(dropConfig.dropRule) do
	    local weight = v[2]
		if r <= weight then
		   heroWeight = v[1]
		   break
		else
		    r = r - weight
		end
	end
	
	if heroWeight == nil then
	   assert()
	end

    local len = #dropConfig.camp
    local index = math.random(1, len)
    local heroID  = HeroDefine.getRandHeroByWeightLvAndCamp(heroWeight, dropConfig.camp[index])
    return heroID
end

local function queryBoxList(human, itemConfig)
	local itemList = itemConfig.cmd[2]
	if not itemList then return end

	local msgRet = Msg.gc.GC_SUIPIAN_ITEM_SUMMON_QUERY
	msgRet.items[0] = #itemList
    for i = 1, msgRet.items[0] do
    	local itemID = itemList[i][1]
    	local itemCnt = itemList[i][2]
        local quality = itemList[i][3]
        Grid.makeItem(msgRet.items[i], itemID, itemCnt, nil, nil, nil, nil, quality)
    end 
	Msg.send(msgRet, human.fd)
end

--碎片英雄召唤预览
function CG_SUIPIAN_HERO_SUMMON_QUERY(human, itemID)
	local itemConfig = ItemExcel.item[itemID]
	if not itemConfig then return end
    
    local cmdStr = itemConfig.cmd[1]
	if cmdStr == "box" or cmdStr == "boxAll" then
		return queryBoxList(human, itemConfig) 
	end

	if itemConfig.get[1] ~= SUMMON_TYPE_TARGET 
		and itemConfig.get[1] ~= SUMMON_TYPE_DROP 
		and itemConfig.get[1] ~= SUMMON_TYPE_HERO_SP 
		and itemConfig.get[1] ~= SUMMON_TYPE_SHENQI_SP then	
		return
	end
	if itemConfig.get[2] ~= SUMMON_SUBTYPE_HERO and itemConfig.get[2] ~= SUMMON_SUBTYPE_EQUIP then
		return
	end
	
	local realItemCnt = 1
	if human.db.bag[itemID] ~= nil then
		realItemCnt = math.floor(human.db.bag[itemID])
	end
	
	if realItemCnt < 1 then
		return
	end
   
	local outItemIDList = nil
	local targetID = nil
	if itemConfig.get[1] == SUMMON_TYPE_TARGET then
		-- 指定目标
		targetID = itemConfig.get[3]
	elseif itemConfig.get[1] == SUMMON_TYPE_DROP then
        local dropID = itemConfig.get[3]
        local dropConfig = DropExcel.dropSuipian[dropID]
		if dropConfig == nil then
			return
		end

        local totalCnt = #dropConfig.dropRule
		local heroWeight
       
        local weightLvAndCampHeros = nil
        for i=1,totalCnt do
			targetID = dropConfig.dropRule[i]
            heroWeight = targetID[1]

            for _, camp in ipairs(dropConfig.camp) do
               weightLvAndCampHeros = HeroDefine.getHeroByWeightLvAndCamp(heroWeight, camp)
               for k, v in pairs(weightLvAndCampHeros) do 
			      outItemIDList = outItemIDList or {}
			      outItemIDList[v] = outItemIDList[v] or 0
			      outItemIDList[v] = outItemIDList[v] + 1
			   end
            end
		end
	elseif itemConfig.get[1] == SUMMON_TYPE_HERO_SP then
    
		-- 英雄条件兑换
		local dropTable = DropSpecial.getDropHeroTable(itemConfig.get[3][1], itemConfig.get[3][2], itemConfig.get[3][3])
		for i = 1, realItemCnt do
			local randTemp = math.random(1, #dropTable)
			targetID = dropTable[randTemp]
			outItemIDList = outItemIDList or {}
			outItemIDList[targetID] = outItemIDList[targetID] or 0
			outItemIDList[targetID] = outItemIDList[targetID] + 1
		end
	elseif itemConfig.get[1] == SUMMON_TYPE_SHENQI_SP then
		-- 神器条件兑换
		local dropTable = DropSpecial.getDropEquipTable(itemConfig.get[3][1], itemConfig.get[3][2], itemConfig.get[3][3], itemConfig.get[3][4])
		for i = 1, realItemCnt do
			local randTemp = math.random(1, #dropTable)
			targetID = dropTable[randTemp]
			outItemIDList = outItemIDList or {}
			outItemIDList[targetID] = outItemIDList[targetID] or 0
			outItemIDList[targetID] = outItemIDList[targetID] + 1
		end
	end
	
	if targetID == nil and outItemIDList == nil then
		assert(nil)
	end
        
	if itemConfig.get[2] == SUMMON_SUBTYPE_HERO then
		local msgRet = Msg.gc.GC_SUIPIAN_HERO_SUMMON_QUERY
		if outItemIDList then
			local len = 0
			for heroID, _ in pairs(outItemIDList) do
				if heroID and HeroExcel.hero[heroID] == nil then
					assert(nil, "why heroID no config " .. heroID .. " " .. itemID)
				end

				if len >= 50 then
					break
				end

		        len = len + 1
		        HeroGrid.makeHeroSimpleByID(msgRet.heroSimple[len], heroID)
		    end

		    msgRet.heroSimple[0] = len
		else
			local heroID = targetID
			msgRet.heroSimple[0] = 1
			HeroGrid.makeHeroSimpleByID(msgRet.heroSimple[1], heroID)
		end
		Msg.send(msgRet, human.fd)		
	else
		local msgRet = Msg.gc.GC_SUIPIAN_ITEM_SUMMON_QUERY
		local cnt = 0
		if outItemIDList then
		    for k, v in pairs(outItemIDList) do
		        cnt = cnt + 1
		        Grid.makeItem(msgRet.items[cnt], k, v)
		    end

		    if cnt > 0 then
				msgRet.items[0] = cnt
				Msg.send(msgRet, human.fd)
			end
		else
			msgRet.items[0] = 1
			Grid.makeItem(msgRet.items[1], targetID, 1)
			Msg.send(msgRet, human.fd)
		end
	end
end


local HEROID_2_SUIPIANID = nil
function getSuipianIDbyHeroID(heroID)
	if not HEROID_2_SUIPIANID then
		HEROID_2_SUIPIANID = {}
		for itemID, itemConfig in pairs(ItemExcel.item) do
			if itemConfig.get[1] == SUMMON_TYPE_TARGET and 
				itemConfig.get[2] == SUMMON_SUBTYPE_HERO then
				local targetID = itemConfig.get[3]
				HEROID_2_SUIPIANID[targetID] = itemID
			end
		end
	end
	return HEROID_2_SUIPIANID[heroID]
end
